package redecolaborativa.interfaceUsuario;

import java.util.Scanner;
import redecolaborativa.excecoes.SessaoInvalidaException;

public class RedeColaborativa {
	private static Fachada fachada;
	private static Scanner input;

	public static void main(String[] args) {
		fachada = Fachada.getInstance();
		input = new Scanner(System.in);
		System.out.println("------------------- Rede Colaborativa -------------------\n");
		menuEntrada();
	}

	private static void menuEntrada() {
		int opcao;
		do {
			imprimeMenuEntrada();
			opcao = lerOpcoes("> ", 1, 3);
			switch (opcao) {
			case 1:	
				cadastraUsuario();
				break;
			case 2: 
				login(); 
				break;
			}
		} while (opcao != 3);
		fachada.encerrarSistema();
	}
	
	private static void cadastraUsuario() {
		try {
			String nome = recebeString("Nome: ");
			String login = recebeString("Login: ");
			String endereco = recebeString("Endereco: ");
			fachada.criarUsuario(login, nome, endereco);
			System.out.println("Usuario cadastrado com sucesso!");
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage());
			cadastraUsuario();
		}
	}
	
	private static void login() {
		String login = recebeString("Login: ");
		try {
			String idSessaoAberta = fachada.abrirSessao(login);
			System.out.printf("----- Seja bem vindo %s! -----", login);
			menuUsuario(idSessaoAberta);
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage());
			menuEntrada();
		} 
	}

	private static void menuUsuario(String idSessaoAberta){
		int opcao; 
		do {
			imprimeMenuUsuario();
			opcao = lerOpcoes("> ", 1, 18);
			switch (opcao) {
			case 1:	
				atualizacoes(idSessaoAberta);
				break;
			case 2: 
				cadastrarItem(idSessaoAberta);
				break;
			case 3: 
				adicionarAmigo(idSessaoAberta);
				break;
			case 4: 
				localizarUsuario(idSessaoAberta);
				break;
			case 5: 
				visualizarPerfil(idSessaoAberta);
				break;
			case 6: 
				devolverItem(idSessaoAberta);
				break;
			case 7: 
				requisitarDevolucaoDeUmItem(idSessaoAberta);
				break;
			case 8: 
				pesquisarItem(idSessaoAberta);
				break;
			case 9: 
				enviarMensagem(idSessaoAberta);
				break;
			case 10: 
				desfazerAmizade(idSessaoAberta);
				break;
			case 11: 
				apagarUmItem(idSessaoAberta);
				break;
			case 12: 
				visualizarRankingDosUsuarios(idSessaoAberta);
				break;
			case 13:
				visualizarHistorico(idSessaoAberta);
				break;
			case 14:
				visualizarHistoricoCompleto(idSessaoAberta);
				break;
			case 15:
				publicarPedido(idSessaoAberta);
				break;
			case 16:
				rePublicarPedido(idSessaoAberta);
				break;
			case 17:
				oferecerItem(idSessaoAberta);
				break;
			}
		} while (opcao != 18);
	}

	private static void atualizacoes(String idSessao){
		int opcao;
		do {
			imprimeMenuAtualizacoes();
			opcao = lerOpcoes("> ", 1, 7);
			switch (opcao) {
			case 1: 
				solicitacoesDeAmizade(idSessao); 
				break;
			case 2: 
				solicitacoesDeItem(idSessao); 
				break;
			case 3: 
				notificacoesDeDevolucaoDeItem(idSessao); 
				break;
			case 4: 
				notificacoesDeRequisicaoDeItem(idSessao); 
				break;
			case 5: 
				notificacoesDeItemLivre(idSessao); 
				break;
			case 6:
				visualizarMensagens(idSessao); 
				break;
			}
		} while (opcao != 7);
	}

	private static void cadastrarItem(String idSessaoAberta){
		try{
			String nome = recebeString("Nome: ");
			String descricao = recebeString("Descricao: ");
			String categoria = recebeString("Digite as categorias dos itens separado por um espaço em branco: ");
			fachada.cadastrarItem(idSessaoAberta, nome, descricao, categoria);
			System.out.println("Item cadastrado com sucesso.");
		}catch(Exception ex){
			System.err.printf("Erro! %s\n\n", ex.getMessage());
			cadastrarItem(idSessaoAberta);
		}
	}

	private static void apagarUmItem(String idSessao){
		try {
			System.out.println(fachada.mostraItensComId(idSessao));
			String opcao = recebeString("1 - Apagar item | 2 - Caso contrario\nEscolha uma opcao: ");
			if(opcao.equals("1")){
				String idItem = recebeString("Digite o id do item que deseja apagar: ");
				fachada.apagarItem(idSessao, idItem);
				System.out.println("Item apagado com sucesso.");
			}
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static void pesquisarItem(String idSessao) {
		try{
			String chave = recebeString("Digite a chave da pesquisa: ");
			String atributo = recebeString("1 - Por nome(Digite nome) | 2 - Por descricao(Digite descricao) | 3 - Por categoria(digite categoria) \nEscolha o atributo de pesquisa: ");
			String tipoOrdenacao = recebeString("1 - Ordem crescente(Digite crescente) | 2 - Ordem decrescente (Digite decrescente)\nEscolha a ordem da pesquisa: ");
			String criterio = recebeString("1 - Data de criacao(Digite datacriacao) | 2 - Reputacao do Usuario(Digite reputacao)\nEscolha a base de pesquisa: ");
			System.out.println(fachada.pesquisarItem(idSessao, chave, atributo, tipoOrdenacao, criterio));
			String opcao = recebeString("\n1 - Para pedir item emprestado | 2 - Caso nao queira\nEscolha uma opcao: ");
			if(opcao.equals("1")) {
				String nomeItem = recebeString("Digite o nome do item que quer pedir emprestado: ");
				int duracao = recebeInt("Digite a duracao do emprestimo: ");
				fachada.requisitarEmprestimo(idSessao, fachada.itemID(nomeItem), duracao);
				System.out.println("Requisicao de emprestimo realizada com sucesso.");
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static void adicionarAmigo(String idSessaoAberta) {
		System.out.println(fachada.retornaUsuariosESeusLogins());
		try {
			String login = recebeString("Digite o login do usuario que voce quer adicionar: ");
			fachada.requisitarAmizade(idSessaoAberta, login);
			System.out.println("Requisicao de amizade feita com sucesso! Aguarde aprovacao.");
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static void desfazerAmizade(String idSessao){
		try {
			System.out.println("Seus amigos sao: " + fachada.getAmigosComLogin(idSessao));
			String opcao = recebeString("1 - Desfazer uma amizade | 2 - Caso contrario\nEscolha uma opcao: ");
			if(opcao.equals("1")){
				String amigo = recebeString("Digite o login do amigo que voce quer excluir: ");
				fachada.desfazerAmizade(idSessao, amigo);
				System.out.println("Amizade desfeita com sucesso.");
			}
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}
	}

	private static void localizarUsuario(String idSessaoAberta){
		/**
		 * TODO Falta visualizar o perfil de algum usuario localizado.
		 */
		String chave = recebeString("Digite a chave da pesquisa: ");
		String atributo = recebeString("Especifique o tipo de pesquisa: 1 - Por nome | 2 - Por endereco\nEscolha uma opcao: ");
		try {
			if(atributo.equals("1")) {
				System.out.println("Usuario pesquisado: " + fachada.localizarUsuario(idSessaoAberta, chave, "nome"));
			} else if(atributo.equals("2")) {
				System.out.println("Usuario pesquisado: " + fachada.localizarUsuario(idSessaoAberta, chave, "endereco"));
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static StringBuilder visualizarPerfilProprio(String idSessaoAberta) throws Exception{
		StringBuilder sb = new StringBuilder();
		sb.append("Meus amigos sao: ");
		sb.append(fachada.getAmigos(idSessaoAberta));
		sb.append("\nMeus itens sao: ");
		sb.append(fachada.getItens(idSessaoAberta));
		return sb;
	}

	private static StringBuilder visualizarPerfilDeOutroUsuario(String idSessaoAberta, String loginAmigo) throws Exception{
		StringBuilder sb = new StringBuilder();
		sb.append("Seus amigos sao: ");
		sb.append(fachada.getAmigos(idSessaoAberta, loginAmigo));
		sb.append("\nSeus itens sao: ");
		sb.append(fachada.getItensComId(idSessaoAberta, loginAmigo));
		return sb;
	}

	private static void visualizarPerfil(String idSessaoAberta){
		try{
			String opcao = recebeString("1 - Para ver seu perfil | 2 - Para ver perfil de amigo\nEscolha uma opcao: ");
			if(opcao.equals("1")){
				System.out.println(visualizarPerfilProprio(idSessaoAberta));
			}else if(opcao.equals("2")){
				System.out.println(fachada.getAmigosComLogin(idSessaoAberta));
				String loginAmigo = recebeString("Digite o login do amigo para ver o perfil dele: ");
				System.out.println(visualizarPerfilDeOutroUsuario(idSessaoAberta, loginAmigo));
				String opcaoDois = recebeString("1 - Se quiser pedir item emprestado | 2- Registrar interesse em item | 3 - Caso nao queira\nEscolha uma opcao: ");
				if(opcaoDois.equals("1")){
					String idItem = recebeString("Digite o id do item que quer pedir emprestado: ");
					int duracao = recebeInt("Digite a duracao do emprestimo: ");
					fachada.requisitarEmprestimo(idSessaoAberta, idItem , duracao);
					System.out.println("Requisicao de emprestimo realizada com sucesso.");
				} else if(opcaoDois.equals("2")){
					String idItem = recebeString("Digite o id do item que quer registrar interesse: ");
					fachada.registrarInteresse(idSessaoAberta, idItem);
				}
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}
	}

	private static void requisitarDevolucaoDeUmItem(String idSessao){
		try {
			fachada.mostraItensQueEmprestou(idSessao);
			String opcao =  recebeString("\n1 - Para requisitar a devolucao do item | 2 - Caso contrario\nEscolha uma opcao: ");
			if(opcao.equals("1")) {
				String idEmprestimo = recebeString("Digite o id de emprestimo do item que voce quer de volta: ");
				fachada.requisitarDevolucao(idSessao, idEmprestimo);
				System.out.println("Requisicao de devolucao de item realizada com sucesso.");
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}
	}

	private static void devolverItem(String idSessao){
		try {
			System.out.println(fachada.retornaItensAdquiridos(idSessao));
			String opcao = recebeString("1 - Para devolver item | 2 - Caso contrario\nEscolha uma opcao: ");
			if(opcao.equals("1")){
				String idEmprestimo = recebeString("Digite o id do emprestimo do item que voce quer devolver: ");
				fachada.devolverItem(idSessao, idEmprestimo);
				System.out.println("Notificacao de devolucao de item realizada com sucesso.");
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static void visualizarRankingDosUsuarios(String idSessao){
		try {
			String categoria = recebeString("Escolha a categoria do ranking: 1 - Ranking Global | 2 - Ranking Entre Amigos\nEscolha uma opcao: ");
			if(categoria.equals("1")) {
				System.out.println(fachada.getRanking(idSessao, "global"));
			} else if(categoria.equals("2")) {
				System.out.println(fachada.getRanking(idSessao, "amigos"));
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}
	
	private static void visualizarHistorico(String idSessaoAberta) {
		try {
			System.out.println(fachada.historicoAtividades(idSessaoAberta));
		} catch (SessaoInvalidaException ex) {
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}

	private static void visualizarHistoricoCompleto(String idSessaoAberta) {
		try {
			System.out.println(fachada.historicoAtividadesConjunto(idSessaoAberta));
		} catch (SessaoInvalidaException ex) {
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}

	private static void publicarPedido(String idSessaoAberta) {
		String nomeItem = recebeString("Nome do item: ");
		String descricaoItem = recebeString("Descricao do item: ");
		try {
			fachada.publicarPedido(idSessaoAberta, nomeItem, descricaoItem);
			System.out.println("Pedido publicado com sucesso.");
		} catch (Exception ex) {
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}
	
	private static void rePublicarPedido(String idSessaoAberta) {
		try {
			fachada.mostraPublicacaoDePedidos();
			String idPublicacaoPedido = recebeString("Digite o id do pedido: ");
			fachada.rePublicarPedido(idSessaoAberta, idPublicacaoPedido);
			System.out.println("Pedido republicado com sucesso.");
		} catch (Exception ex) {
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}
	
	private static void oferecerItem(String idSessaoAberta) {
		try {
			System.out.println(fachada.mostraItensComId(idSessaoAberta));
			String idItem = recebeString("Digite o id do item que deseja oferecer: ");
			fachada.mostraPublicacaoDePedidos();
			String idPublicacaoPedido = recebeString("Digite o id do pedido: ");
			fachada.oferecerItem(idSessaoAberta, idPublicacaoPedido, idItem);
			System.out.println("Item oferecido com sucesso.");
		} catch (Exception ex) {
			System.err.printf("Erro! %s ", ex.getMessage()); 
		}
	}
	
	private static void enviarMensagem(String idSessao){
		try {
			System.out.println(fachada.getAmigosComLogin(idSessao));
			String amigo = recebeString("Digite o login do amigo ao qual voce quer mandar uma mensagem: ");
			String assunto = recebeString("Digite o assunto da mensagem: ");
			String mensagem = recebeString("Digite o corpo da mensagem: ");
			fachada.enviarMensagem(idSessao, amigo, assunto, mensagem);
			System.out.println("Mensagem enviada com sucesso.");
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n ", ex.getMessage());
		}
	}

	private static void visualizarMensagens(String idSessao) {
		try {
			System.out.println(fachada.retornarMensagens(idSessao));
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}

	private static void solicitacoesDeAmizade(String idSessao){
		try{
			System.out.println(fachada.getRequisicoesDeAmizade(idSessao));
			String opcao = recebeString("1 - Se quiser aceitar algum amigo | 2 -  Se quiser rejeitar algum amigo | 3 - Sair\nEscolha uma opcao: ");
			if(opcao.equals("1")){
				String login = recebeString("Digite o login do usuario que voce quer adicionar: ");
				fachada.aprovarAmizade(idSessao, login);
				System.out.println("Aprovacao realizada com sucesso.");
			} else if(opcao.equals("2")){
				String login = recebeString("Digite o login do usuario que voce quer rejeitar: ");
				fachada.rejeitarAmizade(idSessao, login);
				System.out.println("Rejeitado com sucesso.");
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}
	}

	private static void solicitacoesDeItem(String idSessao){
		try {
			System.out.println(fachada.getRequisicoesDeitem(idSessao));
			String opcao = recebeString("1 - Se quiser aceitar algum pedido de emprestimo | 2 - Se quiser rejeitar um pedido | 3 - Sair\nEscolha uma opcao: ");
			if(opcao.equals("1")) {
				String idRequisicaoEmprestimo = recebeString("Digite o ID da requisição do item que voce quer aceitar o emprestimo: ");
				fachada.aprovarEmprestimo(idSessao, idRequisicaoEmprestimo);
				System.out.println("Aprovacao realizada com sucesso.");
			} else if(opcao.equals("2")) {
				String idRequisicaoEmprestimo = recebeString("Digite  o ID da requisição do item que voce quer rejeitar emprestimo: ");
				fachada.rejeitarEmprestimo(idSessao, idRequisicaoEmprestimo);
				System.out.println("Rejeitado com sucesso.");
			}
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}

	}

	private static void notificacoesDeRequisicaoDeItem(String idSessao){
		try {
			System.out.println(fachada.getNotificacaoRequisicaoDeDevolucaoItem(idSessao));
			String string =  recebeString("1 - Se quiser aceitar alguma notificacao de requisicao de item | 2 - Caso nao queira aceitar agora\nEscolha uma opcao: ");
			if(string.equals("1")){
				String nomeItem = recebeString("Digite o nome do item que voce vai devolver: ");
				fachada.devolverItem(idSessao, fachada.itemID(nomeItem));
				System.out.println("Termino de emprestimo realizado com sucesso.");
			}
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}

	}

	private static void notificacoesDeDevolucaoDeItem(String idSessao){
		try {
			System.out.println(fachada.getNotificacaoDeDevolucaoItem(idSessao));
			String string =  recebeString("1 - Se quiser aceitar alguma notificacao de devolucao | 2 - Caso nao queira aceitar agora\nEscolha uma opcao: ");
			if(string.equals("1")){
				String idEmprestimo = recebeString("Digite o ID do emprestimo do item que voce quer aceitar a devolucao: ");
				fachada.confirmarTerminoEmprestimo(idSessao, idEmprestimo);
				System.out.println("Termino de emprestimo realizado com sucesso.");
			}
		} catch (Exception ex) {
			System.err.printf("Erro! %s\n\n", ex.getMessage());
		}

	}

	private static void notificacoesDeItemLivre(String idSessao) {
		try {
			System.out.println(fachada.getNotificacaoDeItemLivre(idSessao));
		} catch (Exception ex) { 
			System.err.printf("Erro! %s\n\n", ex.getMessage()); 
		}
	}
	
	private static int lerOpcoes(String mensagem, int maximo, int minimo) {
		while(true) {
			try {
				System.out.print(mensagem);
				Integer numero = 0;
				do {
					numero = Integer.valueOf(input.nextLine());
				} while(numero < maximo || numero > minimo);
				return numero;
			} catch (NumberFormatException nfe) { }
		}
	}

	private static String recebeString(String mensagem) {
		System.out.print(mensagem);
		return input.nextLine();
	}

	private static int recebeInt(String mensagem){
		System.out.print(mensagem);
		return input.nextInt();
	}

	private static void imprimeMenuEntrada() {
		StringBuilder sb = new StringBuilder();
		sb.append("\nVoce ja eh um usuario cadastrado? Se nao, crie sua conta!\n");
		sb.append("1 - Criar conta.\n");
		sb.append("2 - Login.\n");
		sb.append("3 - Sair.\n");
		System.out.println(sb.toString());
	}

	private static void imprimeMenuUsuario() {
		StringBuilder sb = new StringBuilder();
		sb.append("\nO que deseja fazer? Escolha uma das opcoes abaixo: \n");
		sb.append("1 - Ver atualizacoes.\n");
		sb.append("2 - Cadastrar um item.\n");
		sb.append("3 - Adicionar amigo.\n");
		sb.append("4 - Localizar usuario.\n");
		sb.append("5 - Vizualizar perfil.\n");
		sb.append("6 - Devolver um item.\n");
		sb.append("7 - Requisitar devolucao de um item.\n");
		sb.append("8 - Pesquisar item.\n");
		sb.append("9 - Enviar mensagem.\n");
		sb.append("10 - Desfazer amizade.\n");
		sb.append("11 - Apagar um item.\n");
		sb.append("12 - Visualizar ranking dos usuarios.\n");
		sb.append("13 - Visualizar meu historioco de atividades.\n");
		sb.append("14 - Visualizar historico completo de atividades.\n");
		sb.append("15 - Publicar pedido.\n");
		sb.append("16 - Republicar pedido.\n");
		sb.append("17 - Oferecer item.\n");
		sb.append("18 - Sair.\n");
		System.out.println(sb.toString());	
	}

	private static void imprimeMenuAtualizacoes() {
		StringBuilder sb = new StringBuilder();
		sb.append("1 - Solicitacoes de amizade.\n");
		sb.append("2 - Solicitacoes de item.\n");
		sb.append("3 - Notificacoes de devolucao de item.\n");
		sb.append("4 - Notificacoes de requisicao de item.\n");
		sb.append("5 - Notificacoes de item livre.\n");
		sb.append("6 - Ver mensagens.\n");
		sb.append("7 - Sair.\n");
		System.out.println(sb.toString());
	}	
}